package com.zzjson.aop.introductions;

import com.zzjson.aop.service.MessageService;
import com.zzjson.aop.service.SimpleMessageServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

/**
 * <p>****************************************************************************</p>
 * <li>Description : TODO </li>
 * <li>Version     : 1.0.0</li>
 * <li>Creation    : 2021年02月19日</li>
 * <li>@author     : zzy0_0</li>
 * </ul>
 * <p>****************************************************************************</p>
 */
@Aspect
@Slf4j
public class AnnotationWithIntroAspect {

	@DeclareParents(value = "com.zzjson.aop.service.*+", defaultImpl = SimpleMessageServiceImpl.class)
	public static MessageService messageService;


	/**
	 * 配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
	 * 切点的集合，这个表达式所描述的是一个虚拟面（规则）
	 * 就是为了Annotation扫描时能够拿到注解中的内容
	 */
	@Pointcut("execution(* com.zzjson.aop.service..*(..))&&" +
			"@annotation(com.zzjson.aop.annoation.MyLog)")
	public void aspect() {
	}

	@Before("aspect()")
	public void before(JoinPoint joinPoint) {
		log.info("before " + joinPoint);
	}


	/**
	 * 配置后置通知,使用在方法aspect()上注册的切入点
	 */
	@After("aspect()")
	public void after(JoinPoint joinPoint) {
		log.info("after " + joinPoint);
	}

	//配置环绕通知,使用在方法aspect()上注册的切入点
	@Around("aspect()")
	public void around(JoinPoint joinPoint) {
		long start = System.currentTimeMillis();
		try {
			((ProceedingJoinPoint) joinPoint).proceed();
			long end = System.currentTimeMillis();
			log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
		} catch (Throwable e) {
			long end = System.currentTimeMillis();
			log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
		}
	}

	//配置后置返回通知,使用在方法aspect()上注册的切入点
	@AfterReturning("aspect()")
	public void afterReturn(JoinPoint joinPoint) {
		log.info("afterReturn " + joinPoint);
	}

	//配置抛出异常后通知,使用在方法aspect()上注册的切入点
	@AfterThrowing(pointcut = "aspect()", throwing = "ex")
	public void afterThrow(JoinPoint joinPoint, Exception ex) {
		log.info("afterThrow " + joinPoint + "\t" + ex.getMessage());
	}
}